/*----------------------------- L610部分-------------------------------*/
#include <HardwareSerial.h>
#include "L610.h"

//4G激活上网AT指令集长度
int ATlength = 6;  

//4G激活上网AT指令集
String ATcommands[]=
{
  {"AT"},
  //{"AT+CPIN?"},  //SIM卡
  {"AT+CSQ"},
  {"AT+CREG?"},
  {"AT+CGREG?"},
  // {"AT+GTSET=\"IPRFMT\",0"}
  {"AT+MIPCALL?"},
  {"AT+MIPCALL=1"}
};
//4G激活上网AT指令集期望的回复
String ATrepids[]=
{
  {"OK"},
  //{"+CPIN:READY"},  //SIM卡
  {"+CSQ:"},
  {"+CREG:"},
  {"+CGREG:"},
  // {"AT+GTSET=\"IPRFMT\",0"},
  {"OK"},
  {"OK"}
};

// 初始化ESP32和L610模块之间的串口通信 (使用硬件串口Serial1)
extern HardwareSerial SerialL610;

/*函数名称: SendCmdToL610
*说明: esp32向L610发送指令
*参数: data: 要发送的指令  res:期望L610返回的消息
*返回值:无
*/
void SendCmdToL610(String data,const char* res)
{
  SerialL610.println(data);  //向SerialL610串口发送数据
  Serial.println(data);

  delay(10);
  while(SerialL610.available())
  {
    String rpy=SerialL610.readString();  //读取缓存数组内的数据并打印
    if(rpy.indexOf(res)>=0)  //在SerialL610串口接收数据的缓存数组内查找是否存在与res相同的内容
    {
      Serial.println(rpy);
      break;
    }
    else
    {
      Serial.println("error");
      SerialL610.println(data);
    }
    delay(10);
  }
}

/*函数名称: L610_Attach
*说明: esp32向L610发送指令使L610联网
*参数: reset: 是否为重置状态，为真值才进行联网
*返回值:无
*/
//初始化、4G联网
void L610_Attach(bool reset)
{
  SerialL610.println("ATE1");  //令L610开启回显模式
  if(reset)
  {
    int i=0;
    while(i<ATlength)  //按顺序发送AT指令集
    {
      SendCmdToL610(ATcommands[i],ATrepids[i].c_str());
      i++; 
    }
  }
}

/*-------------------------MQTT部分-------------------------*/  
#include <string.h>
#include "L610.h"
#ifdef MQTT
/*函数名称: MqttConnect
*说明: 通过L610与云平台建立MQTT连接
*参数: devide_id: 设备唯一标识号  user_name: 云平台对应设备的用户名	 password：云平台对应设备的密钥 ClientIDStr： 云平台对应设备的client_id 
mqttServer_ip：待连接的云平台ip地址  mqttServer_Port：待连接的云平台mqtt协议端口号
CleansessionFlag：遗嘱标志位(0:保留所有订阅主题,1:清楚所有订阅主题) Qos: 服务质量等级(0-2，部分平台不支持QoS 等级 2) Keepalive_Time：心跳保活时间
*返回值:无
*/
void MqttConnect(const char* device_id, const char* user_name,const char* password,const char* ClientIDStr, const char* mqttServer_ip,const char* mqttServer_Port,
const char* CleansessionFlag ,const char* Keepalive_Time )
{
  //先为本设备配置mqtt鉴权凭证和设备名称
  String cmd;
  cmd = cmd + "AT+MQTTUSER=";
  cmd = cmd + device_id;
  cmd = cmd + ",\"";
  cmd = cmd + user_name;
  cmd = cmd + "\",\"";
  cmd = cmd + password;
  cmd = cmd + "\",\"";
  cmd = cmd + ClientIDStr;
  cmd = cmd + "\"";
  SendCmdToL610(cmd,"OK");

  //再建立mqtt连接
  cmd = "";
  cmd = cmd + "AT+MQTTOPEN=";
  cmd = cmd + device_id;
  cmd = cmd + ",\"";
  cmd = cmd + mqttServer_ip;
  cmd = cmd + "\",";
  cmd = cmd + mqttServer_Port;
  cmd = cmd + ",";
  cmd = cmd + CleansessionFlag;
  cmd = cmd + ",";
  cmd = cmd + Keepalive_Time;
  SendCmdToL610(cmd,"OK");
}

/*函数名称: L610_MQTTSub
*说明: 订阅某个主题的消息内容
*参数: devideid: 设备唯一标识号  topic: 待订阅的主题	 Qos: 服务质量等级(0-2，部分平台不支持QoS 等级 2)
*返回值:无
*/
void L610_MQTTSub(const char* device_id, const char* topic,const int QoS)
{
  String cmd;
  cmd = cmd + "AT+MQTTSUB=";
  cmd = cmd + device_id;
  cmd = cmd + ",\"";
  cmd = cmd + topic;
  cmd = cmd + "\",";
  cmd = cmd + (char*)QoS;
  SendCmdToL610(cmd,"OK");

}

/*函数名称: L610_MQTTPub
*说明: 发布某个主题的消息内容
*参数:  devideid: 设备唯一标识号  topic: 待发布的主题  Qos: 服务质量等级(0-2，部分平台不支持QoS 等级 2)  remain_flag: 保留消息标志   data: 待发送的主题内容
*返回值:无
*/
void L610_MQTTPub(const char* device_id, const char* topic,const int QoS,const int remain_flag,String data)
{
  String cmd;
  cmd = cmd + "AT+MQTTPUB=";
  cmd = cmd + device_id;
  cmd = cmd + ",\"";
  cmd = cmd + topic;
  cmd = cmd + "\",";
  cmd = cmd + QoS;
  cmd = cmd + ",";
  cmd = cmd + remain_flag;
  cmd = cmd + ",";
  cmd = cmd + data.length();
  SendCmdToL610(cmd,">");
  SendCmdToL610(data,"OK");
}
#endif

/*-------------------------TCP部分-------------------------*/  
#include <string.h>
#include "L610.h"
#ifdef TCP

/*函数名称: TCPConnect
*说明: 通过L610与云平台建立TCP连接
*参数: socket_id: socket唯一标识号  server_ip: 待连接的云平台TCP/UDPip地址	 server_port: 待连接的云平台TCP/UDP协议端口号 type: 待建立的连接类型(TCP/UDP)
*返回值:无
*/
void TCPConnect(const char* socket_id,const char* server_ip,const char* server_port,const char* type)
{
  String cmd = "AT+MIPOPEN=";
  cmd = cmd + socket_id;
  cmd = cmd + ",,\"";
  cmd = cmd + server_ip;
  cmd = cmd + "\",";
  cmd = cmd + server_port;
  cmd = cmd + ",0";
  SendCmdToL610(cmd,"OK");
}

/*函数名称: SendDataToTCPServer
*说明: 发送消息到tcp或udp服务器
*参数: socket_id: socket唯一标识号  data: 待发送的内容(十六进制形式，需在云平台端编写脚本将十六进制转换为ASCⅡ类型才可正确解码)
*返回值:无
*/
void SendDataToTCPServer(const char* socket_id,String data)
{
  String cmd = "AT+MIPSEND=";
  cmd = cmd + socket_id;
  cmd = cmd + ",";
  cmd = cmd + data.length();
  SendCmdToL610(cmd,">");
  SendCmdToL610(data,"OK");
}
#endif
